package com.platform.qujia.service.impl;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.platform.qujia.dao.ClassSettlementMapper;
import com.platform.qujia.enums.CardRecordType;
import com.platform.qujia.enums.PayTypeEnum;
import com.platform.qujia.param.request.AutoPayWay;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.CardClassSettDto;
import com.platform.qujia.pojo.dto.OilEngineDto;
import com.platform.qujia.pojo.vo.changeClassSettlement4User;
import com.platform.qujia.service.ClassSettlementCardService;
import com.platform.qujia.service.ClassSettlementService;
import com.platform.qujia.utils.BGResult;
import com.platform.qujia.utils.JsonUtils;
import com.platform.qujia.utils.MathUtil;
import com.platform.qujia.utils.exception.CustomException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 班结Service业务层处理
 * 
 * @author qujia
 * @date 2021-11-27
 */
@Service("classSettlementService")
public class ClassSettlementServiceImpl implements ClassSettlementService
{
    private static final Logger log = LoggerFactory.getLogger(ClassSettlementServiceImpl.class);
    @Resource
    private ClassSettlementMapper classSettlementMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${qujia.bgBaseUrl}")
    private String bgBaseUrl;
    @Autowired
    private ClassSettlementCardService classSettlementCardService;

    /**
     * 查询班结汇总列表
     *
     * @param classSettlement 班结
     * @return 班结
     */
    @Override
    public List<ClassSettlement> selectClassSettlementSummaryList(ClassSettlement classSettlement)
    {
        return classSettlementMapper.selectClassSettlementSummaryList(classSettlement);
    }

    @Override
    public List<ClassSettlement> selectClassSettlementSummary4POSList(Map<String,Object> params)
    {
        return classSettlementMapper.selectClassSettlementSummary4POSList(params);
    }
    @Override
    public List<ClassSettlement> selectClassSettlement4User4POSList(Map<String,Object> params)
    {
        return classSettlementMapper.selectClassSettlement4User4POSList(params);
    }

    @Override
    public BigDecimal forKillCouponAmt(Map<String, Object> params) {
        BigDecimal  forKillCouponAmt =  BigDecimal.ZERO;
        ClassSettlementCard forKillCoupon=  classSettlementMapper.forKillCouponAmt(params);
        forKillCouponAmt =forKillCoupon.getAmt();
        return forKillCouponAmt;
    }
    @Override
    public ClassSettlement querySuperPay(Map<String, Object> params) {
        return classSettlementMapper.querySuperPay(params);
    }

    /**
     * 新增班结
     * 
     * @param classSettlement 班结
     * @return 结果
     */
    @Override
    public int insertClassSettlement(ClassSettlement classSettlement)
    {
        classSettlement.setCreateTime(new Date());
        return classSettlementMapper.insertClassSettlement(classSettlement);
    }
    /**
     * 新增油机班结
     *
     * @param classSettlementOilmachine 班结
     * @return 结果
     */
    @Override
    public int insertClassSettlementOilmachine(ClassSettlementOilmachine classSettlementOilmachine)
    {

        return classSettlementMapper.insertClassSettlementOilmachine(classSettlementOilmachine);
    }

    @Override
    public BigDecimal forActualRechargeReceivedAmt(BigDecimal actualRechargeReceivedAmt,Map<String, Object> params)
    {
        actualRechargeReceivedAmt = (actualRechargeReceivedAmt != null) ? actualRechargeReceivedAmt : BigDecimal.ZERO;
        ClassSettlement physicalCard=  classSettlementMapper.queryPhysicalCard(params);
        ClassSettlement fleetCard=  classSettlementMapper.queryFleetCard(params);
        ClassSettlement superPay = classSettlementMapper.querySuperPay(params);
        if (actualRechargeReceivedAmt != null) {
            BigDecimal physicalCardAmt = physicalCard.getAmt() != null ? physicalCard.getAmt() : BigDecimal.ZERO;
            BigDecimal fleetCardAmt = fleetCard.getAmt() != null ? fleetCard.getAmt() : BigDecimal.ZERO;
            BigDecimal superPayAmt = superPay.getAmt() != null ? superPay.getAmt() : BigDecimal.ZERO;
            actualRechargeReceivedAmt = actualRechargeReceivedAmt.add(physicalCardAmt).add(fleetCardAmt).add(superPayAmt);

        }
        return actualRechargeReceivedAmt;
    }

    @Override
    public List<ClassSettlementOilmachine> selectAllClassSettlementOilmachines(String classNo)
    {

        return classSettlementMapper.selectAllClassSettlementOilmachines(classNo);
    }
    public String queryClassDayOrNight(Long stationId, Date createEndTime) {
        Map<String, Object> params = new HashMap<>();
        params.put("stationId", stationId);
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        String formattedStartTime = format.format(createEndTime);
        params.put("createEndTime", formattedStartTime);
        return classSettlementMapper.queryClassDayOrNight(params);
    }

    public List<Map<String, Object>> queryGroupByOilGunForOrder(Map<String, Object> params) {
        return classSettlementMapper.queryGroupByOilGunForOrder(params);
    }
    @Override
    public void insertAboutOil(Map<String, Object> params,String no,String classEndTime,Long stationId) {
        List<Map<String, Object>> queryGroupByOilGun = this.queryGroupByOilGunForOrder(params);
        Iterator<Map<String, Object>> iterator2 = queryGroupByOilGun.iterator();
        while (iterator2.hasNext()) {
            Map<String, Object> map = iterator2.next();
            if (!map.containsKey("oil_gun")) {
                iterator2.remove();
            }
        }
        List<OilEngineDto> newQueryGroupByOilGun = classSettlementMapper.classSettlementOilEngineSum(params);
        List<String> oilGunListA = new ArrayList<>();
        List<String> oilGunListB = new ArrayList<>();
        if (queryGroupByOilGun.size() > 0 && newQueryGroupByOilGun.size() > 0) {
            for (Map<String, Object> map : queryGroupByOilGun) {
                String oilGun = map.get("oil_gun").toString();
                map.put("class_no",no);
                map.put("class_end_time",classEndTime);
                map.put("station_id",stationId);
                oilGunListA.add(oilGun); // 存储a列表的油枪数据
                oilGunListB.clear();
                for (OilEngineDto oilEngineDto : newQueryGroupByOilGun) {
                    oilGunListB.add(oilEngineDto.getOilGun());
                    if (oilEngineDto != null && oilEngineDto.getOilGun() != null && oilEngineDto.getOilGun().equals(oilGun)) {
                        map.put("oil_price", oilEngineDto.getOilPrice());
                        map.put("class_no",no);
                        map.put("class_end_time",classEndTime);
                        map.put("station_id",stationId);
                        map.put("order_liters", oilEngineDto.getOrderLiters());
                        map.put("oil_name", oilEngineDto.getOilName());
                        map.put("startFlowMeter", oilEngineDto.getStartFlowMeter());
                        map.put("endFlowMeter", oilEngineDto.getEndFlowMeter());
                    }
                }
            }
            List<String> difference = new ArrayList<>();
            for (String value : oilGunListB) {
                if (!oilGunListA.contains(value)) {
                    difference.add(value);
                }
            }
            for (OilEngineDto oilEngineDto : newQueryGroupByOilGun) {
                for (String oilGun : difference) {

                    if (oilEngineDto != null && oilEngineDto.getOilGun() != null && oilEngineDto.getOilGun().equals(oilGun)) {

                        Map<String, Object> map = new HashMap<>();
                        map.put("class_no",no);
                        map.put("class_end_time",classEndTime);
                        map.put("station_id",stationId);
                        map.put("oil_gun", oilEngineDto.getOilGun());
                        map.put("oil_price", oilEngineDto.getOilPrice());
                        map.put("order_liters", oilEngineDto.getOrderLiters());
                        map.put("oil_name", oilEngineDto.getOilName());
                        map.put("startFlowMeter", oilEngineDto.getStartFlowMeter());
                        map.put("endFlowMeter", oilEngineDto.getEndFlowMeter());
                        queryGroupByOilGun.add(map);
                    }
                }
            }

        } else if (queryGroupByOilGun.size() == 0 && newQueryGroupByOilGun.size() > 0) {
            for (OilEngineDto oilEngineDto : newQueryGroupByOilGun) {
                if (oilEngineDto != null && oilEngineDto.getOilGun() != null) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("class_no",no);
                    map.put("class_end_time",classEndTime);
                    map.put("station_id",stationId);
                    map.put("oil_gun", oilEngineDto.getOilGun());
                    map.put("oil_price", oilEngineDto.getOilPrice());
                    map.put("order_liters", oilEngineDto.getOrderLiters());
                    map.put("oil_name", oilEngineDto.getOilName());
                    map.put("startFlowMeter", oilEngineDto.getStartFlowMeter());
                    map.put("endFlowMeter", oilEngineDto.getEndFlowMeter());
                    queryGroupByOilGun.add(map);

                }
            }
        }
        List<OilOmeter> oilOmeters =  classSettlementMapper.selectByStationId(stationId);
        for (OilOmeter oilOmeter:oilOmeters){
            oilOmeter.setClassEndTime(classEndTime);
            oilOmeter.setClassNo(no);
            classSettlementMapper.insertSelective(oilOmeter);
        }
        classSettlementMapper.insertAboutOilEngine(queryGroupByOilGun);

    }
    @Override
    public void selectChange4User4POSListForOrder(Map<String, Object> params) {
        List<changeClassSettlement4User> changeClassSettlement4User=classSettlementMapper.selectChange4User4POSListForOrder(params);
        for (com.platform.qujia.pojo.vo.changeClassSettlement4User changeClassSettlement :changeClassSettlement4User){
            changeClassSettlement.setPresentAmount(BigDecimal.ZERO);
            changeClassSettlement.setTotalDiscountAmt(BigDecimal.ZERO);
            changeClassSettlement.setReceivableAmt(changeClassSettlement.getAmt());
            changeClassSettlement.setClassNo( params.get("no").toString());
            classSettlementMapper.addChange4User4POSListForOrder(changeClassSettlement);
        }

    }
    /**
     * 查询未班结信息
     *
     * @param params
     * @return 结果
     */
    @Override
    public List<ClassSettlement> queryUntreatedData(Map<String,Object> params)
    {
        return classSettlementMapper.queryUntreatedData(params);
    }
    /***
     * 充值合计(包括退款)
     * @param params
     * @return
     */
    @Override
    public BigDecimal getTotalAmtByConditions(Map<String, Object> params) {
        return classSettlementMapper.getTotalAmtByConditions(params);
    }

    @Override
    public BigDecimal getTotalPresentAmtByConditions(Map<String, Object> params) {
        return classSettlementMapper.getTotalPresentAmtByConditions(params);
    }
    /**
     * 查询班结内通联支付的订单
     *
     * @param params
     * @return 结果
     */
    @Override
    public List<ClassSettlement> queryPayWayData(Map<String,Object> params)
    {
        return classSettlementMapper.queryPayWayData(params);
    }


    /**
     * 查询最近的班结信息
     *
     * @param classSettlement
     * @return 结果
     */
    public ClassSettlement QueryMaxClass(ClassSettlement classSettlement){
        return classSettlementMapper.QueryMaxClass(classSettlement);
    }

    @Override
    public Map<String,Object> queryLastEndTime(Map<String,Object> params){
        return classSettlementMapper.queryLastEndTime(params);
    }
    @Override
    public List<Map<String,Object>> queryGroupByPayType(Map<String,Object> params){
        return classSettlementMapper.queryGroupByPayType(params);
    }
    @Override
    public List<Map<String,Object>> queryGroupByUser(Map<String,Object> params){
        return classSettlementMapper.queryGroupByUser(params);
    }

    @Override
    public String createClassSettlementBGApi(ClassSettlement classSettlement) {
        Map<?, ?> map = null;
        try {
            map = JsonUtils.objectToMap(classSettlement);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new CustomException("参数异常");
        }
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(bgBaseUrl+"/station/classSettlement/anony/createClassSe");
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                builder.queryParam(String.valueOf(entry.getKey()), entry.getValue());
            }
        }
        BGResult result = restTemplate.getForObject(builder.build().toString(), BGResult.class);
        if (result.getCode()!= BGResult.SUCCESS_CODE) {
            throw new CustomException("创建班结失败，"+result.getMsg());
        }
        Map<String, Object> data = (Map<String, Object>) result.getData();
        return (String) data.get("classNo");
    }

    @Override
    public BGResult customerPointsRecordApi(CustomerPointsRecordApi customerPointsRecordApi) {

        Map<?, ?> map = null;
        try {
            map = JsonUtils.objectToMap(customerPointsRecordApi);
        } catch (IOException e) {
            log.error(e.getMessage(), e);

        }
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(bgBaseUrl+"/integral/record/anony/list");
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                builder.queryParam(String.valueOf(entry.getKey()), entry.getValue());
            }
        }
        BGResult result = restTemplate.getForObject(builder.build().toString(), BGResult.class);
        return result;
    }

    @Override
    public void changeAutoPayWayBGApi(AutoPayWay autoPayWay) {
        autoPayWay.setWayPayWay("1");
        Map<?, ?> map = null;
        try {
            map = JsonUtils.objectToMap(autoPayWay);
        } catch (IOException e) {
            log.error(e.getMessage(), e);

        }
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(bgBaseUrl+"/payWay/info/anony/selectAutoPayWay");
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                builder.queryParam(String.valueOf(entry.getKey()), entry.getValue());
            }
        }
        BGResult result = restTemplate.getForObject(builder.build().toString(), BGResult.class);

    }

    @Override
    public Map<String,Object> getClassSettlementInfoBGApi(String classNo) {
        BGResult result = restTemplate.getForObject(bgBaseUrl+"/station/classSettlement/anony/{classNo}", BGResult.class,classNo);
        if (result.getCode()!= BGResult.SUCCESS_CODE) {
            throw new CustomException("获取班结信息失败，"+result.getMsg());
        }
        return (Map<String, Object>) result.getData();
    }

    @Override
    public Map<String, Object> getClassSettlementInfo(String classNo) {
        return null;
    }

    @Override
    public Map<String,Object> createAndGetClassSettlement(ClassSettlement classSettlement) {
        String classNo = createClassSettlementBGApi(classSettlement);
        return getClassSettlementInfoBGApi(classNo);
    }

    @Override
    public List<ClassSettlementCard> getTransactionSummary(CardClassSettDto settDto, Map<String, Object> params) {
        List<ClassSettlementCard> transactionSummary = new ArrayList<>();
        List<ClassSettlementCard> settCardList =settDto.getSettlementCardList();
        ClassSettlementCard wxrefClassSettlementCard = new ClassSettlementCard();
        ClassSettlementCard posrefClassSettlementCard = new ClassSettlementCard();
        for (ClassSettlementCard settCard : settCardList) {
            if (settCard.getPayType() != null && settCard.getPayType().equals(CardRecordType.WX_REFUND.getKey())) {
                wxrefClassSettlementCard = settCard;
            }
            if (settCard.getPayType() != null && settCard.getPayType().equals(CardRecordType.POS_REFUND.getKey())) {
                posrefClassSettlementCard = settCard;
            }
        }
        for(ClassSettlementCard settCard:settCardList){
            if (settCard.getPayType() != null && settCard.getPayType().equals("imp")) {
                transactionSummary.add(settCard);
            }else if(settCard.getPayType() != null && settCard.getPayType().equals("pos")) {
                settCard.setAmt(settCard.getAmt().subtract(posrefClassSettlementCard.getAmt()== null ? BigDecimal.ZERO : posrefClassSettlementCard.getAmt()));
                settCard.setGiveAmt(settCard.getGiveAmt().subtract(posrefClassSettlementCard.getGiveAmt()== null ? BigDecimal.ZERO : posrefClassSettlementCard.getGiveAmt()));
                if (settCard.getOrderCount() != null && posrefClassSettlementCard.getOrderCount() != null) {
                    settCard.setOrderCount(settCard.getOrderCount() - posrefClassSettlementCard.getOrderCount());
                }
                if (settCard.getOrderCount() == null || settCard.getOrderCount() != 0) {
                    transactionSummary.add(settCard);
                }
            }else if (settCard.getPayType() != null && settCard.getPayType().equals("wx")) {
                settCard.setAmt(settCard.getAmt().subtract(wxrefClassSettlementCard.getAmt()== null ? BigDecimal.ZERO : wxrefClassSettlementCard.getAmt()));
                settCard.setGiveAmt(settCard.getGiveAmt().subtract(wxrefClassSettlementCard.getGiveAmt()== null ? BigDecimal.ZERO : wxrefClassSettlementCard.getGiveAmt()));
                if (settCard.getOrderCount() != null && wxrefClassSettlementCard.getOrderCount() != null) {
                    settCard.setOrderCount(settCard.getOrderCount() - wxrefClassSettlementCard.getOrderCount());
                }
                if (settCard.getOrderCount() == null || settCard.getOrderCount() != 0) {
                    transactionSummary.add(settCard);
                }
            }
        }

        ClassSettlementCard physicalCardInXj = classSettlementMapper.queryPhysicalCardInXj(params);
        physicalCardInXj.setPayType("dkqxj");
        transactionSummary.add(physicalCardInXj);
        ClassSettlementCard physicalCardInRef = classSettlementMapper.queryPhysicalCardInRef(params);
        physicalCardInRef.setPayType("dkqref");
        transactionSummary.add(physicalCardInRef);
        ClassSettlementCard physicalCardInWxPos = classSettlementMapper.queryPhysicalCardInWxPos(params);
        physicalCardInWxPos.setPayType("dkqwxpos");
        physicalCardInWxPos.setAmt(MathUtil.subtract(physicalCardInWxPos.getAmt(),physicalCardInRef.getAmt()));
        physicalCardInWxPos.setOrderCount(MathUtil.subtract(physicalCardInWxPos.getOrderCount(),physicalCardInRef.getOrderCount()));
        transactionSummary.add(physicalCardInWxPos);


//        ClassSettlementCard physicalCardC = new ClassSettlementCard();
//        physicalCardC.setPayType(PayTypeEnum.dkq.getType());
//        physicalCardC.setAmt(MathUtil.add(physicalCardInXj.getAmt(),physicalCardInWxPos.getAmt()));
//        physicalCardC.setWithdrawalAmount(MathUtil.add(null,physicalCard.getTotalWithdrawalAmount()));
//        physicalCardC.setOrderCount(physicalCard.getOrderCount());
//        transactionSummary.add(physicalCardC);


        ClassSettlement fleetCard=  classSettlementMapper.queryFleetCard(params);
        if (fleetCard.getOrderCount()!=null && fleetCard.getOrderCount()!=0) {
            ClassSettlementCard fleetCardC = new ClassSettlementCard();
            fleetCardC.setPayType(PayTypeEnum.cdk.getType());
            fleetCardC.setAmt(MathUtil.add(null,fleetCard.getAmt()));
            fleetCardC.setWithdrawalAmount(MathUtil.add(null,fleetCard.getTotalWithdrawalAmount()));
            fleetCardC.setOrderCount(fleetCard.getOrderCount());
            transactionSummary.add(fleetCardC);
        }
//        ClassSettlementCard alltransaction = new ClassSettlementCard();
//        alltransaction.setPayType("合计");
//        BigDecimal totalAmt = BigDecimal.ZERO;
//        BigDecimal totalWithdrawalAmount = BigDecimal.ZERO;
//        Long totalOrderCount = 0L;
//
//        for(ClassSettlementCard transaction:transactionSummary) {
//            if (transaction.getAmt() != null) {
//                totalAmt = totalAmt.add(transaction.getAmt());
//            }
//            if (transaction.getWithdrawalAmount() != null) {
//                totalWithdrawalAmount = totalWithdrawalAmount.add(transaction.getWithdrawalAmount());
//            }
//            if (transaction.getOrderCount() != null) {
//                totalOrderCount = totalOrderCount + transaction.getOrderCount();
//            }
//        }
//
//        alltransaction.setAmt(totalAmt);
//        alltransaction.setWithdrawalAmount(totalWithdrawalAmount);
//        alltransaction.setOrderCount(totalOrderCount);
//        transactionSummary.add(alltransaction);
        return transactionSummary;
    }

    @Override
    public List<ClassSettlement> querySummaryByClassNoAllData(Map<String, Object> params, CardClassSettDto settDto) {
        List<ClassSettlement> summaryByClassNo = classSettlementMapper.querySummaryByClassNo(params);

        BigDecimal actualRechargeReceivedAmt = settDto.getTotalRechargeAmt();

        BigDecimal totalRechargeWithdrawalAmount = settDto.getTotalWithdrawalAmount();
        BigDecimal totalRechargeRefundAmt = settDto.getTotalRefundAmt();
//        //        消费合计退款
//        summaryMap.put("consumptionRefundAmt", consumptionRefundAmt);
////        优惠金额
//        summaryMap.put("totalDiscountAmt", totalDiscountAmt);
////        充值合计提现
//        summaryMap.put("totalRechargeWithdrawalAmount", totalRechargeWithdrawalAmount);
////        充值合计退款
//        summaryMap.put("totalRechargeRefundAmt", totalRechargeRefundAmt);
////        到账总金额
//        summaryMap.put("allAmt", allAmt);

        BigDecimal allAmt = BigDecimal.ZERO;//到账总金额
        BigDecimal consumptionRefundAmt = BigDecimal.ZERO;//消费合计退款
        if (summaryByClassNo != null && !summaryByClassNo.isEmpty()) {
            ClassSettlement firstItem = summaryByClassNo.get(0);
            if (firstItem != null) {
                BigDecimal discountAmt = firstItem.getDiscountAmt();
                BigDecimal superPayAmt = firstItem.getSuperPayAmt();
                BigDecimal discountCouponAmt = firstItem.getDiscountCouponAmt();
                BigDecimal actualTotalAmt = firstItem.getActualRechargeReceivedAmt();
                if (discountAmt != null && discountCouponAmt != null) {
                    BigDecimal totalDiscountAmt = discountAmt.add(discountCouponAmt);
                    firstItem.setTotalDiscountAmt(totalDiscountAmt);

                }
                BigDecimal totalWithdrawalAmount = firstItem.getTotalWithdrawalAmount();
                BigDecimal amt = summaryByClassNo.get(0).getAmt();
                BigDecimal nodzkAmt = summaryByClassNo.get(0).getNodzkAmt();
                allAmt = nodzkAmt != null ? nodzkAmt.add(actualTotalAmt != null ? actualTotalAmt : BigDecimal.ZERO) : BigDecimal.ZERO;
                firstItem.setAllAmt(allAmt);
                firstItem.setTotalRechargeWithdrawalAmount(totalRechargeWithdrawalAmount);
                firstItem.setTotalRechargeRefundAmt(totalRechargeRefundAmt);
                firstItem.setTotalWithdrawalAmount(MathUtil.add(superPayAmt,totalWithdrawalAmount));
                firstItem.setTotalWithdrawalAmount(MathUtil.add(firstItem.getSaleActivityAmt(),firstItem.getTotalWithdrawalAmount()));
            }
        }
        return summaryByClassNo;
    }

    @Override
    public List<String> queryClassNoByPayDate(Integer stationId,Date payDate) {
        return classSettlementMapper.queryClassNoByPayDate(stationId, payDate);
    }

    @Override
    public int updateClassSettlementStatus(String classNo) {
        return classSettlementMapper.updateClassSettlementStatus(classNo);
    }
}
